#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define KEY 6
char *keyword[KEY] = { "for", "if", "then", "else", "while", "do" };
char id[1024];
int num;
int token;

void lexical(FILE *fp) {
	//char x = getc(fp);

	num = 0;
	strcpy(id, "\0");

	//process x
	//process each regex here
	//store the result in global variables id, num, or token
	//in case of backtrack, use
	//ungetc(x, fp);
	while (match(fp, " ") || match(fp, "\n") || match(fp, "\t"))
	{
	}


	if (match(fp, "for"))
	{
		strcpy(id, "for");
		token = 1;
	}
	else if (match(fp, "if"))
	{
		strcpy(id, "if");
		token = 2;
	}
	else if (match(fp, "then"))
	{
		strcpy(id, "then");
		token = 3;
	}
	else if (match(fp, "else"))
	{
		strcpy(id, "else");
		token = 4;
	}
	else if (match(fp, "while"))
	{
		strcpy(id, "while");
		token = 5;
	}
	else if (match(fp, "do"))
	{
		strcpy(id, "do");
		token = 6;
	}
	else if (match(fp, "+"))
	{
		strcpy(id, "+");
		token = 13;
	}
	else if (match(fp, "-"))
	{
		strcpy(id, "-");
		token = 14;
	}
	else if (match(fp, "*"))
	{
		strcpy(id, "*");
		token = 15;
	}
	else if (match(fp, "/"))
	{
		strcpy(id, "/");
		token = 16;
	}
	else if (match(fp, ":="))
	{
		strcpy(id, ":=");
		token = 18;
	}
	else if (match(fp, ":"))
	{
		strcpy(id, ":");
		token = 17;
	}
	else if (match(fp, "<>"))
	{
		strcpy(id, "<>");
		token = 21;
	}
	else if (match(fp, "<="))
	{
		strcpy(id, "<=");
		token = 22;
	}
	else if (match(fp, "<"))
	{
		strcpy(id, "<");
		token = 20;
	}
	else if (match(fp, ">="))
	{
		strcpy(id, ">=");
		token = 24;
	}
	else if (match(fp, ">"))
	{
		strcpy(id, ">");
		token = 23;
	}
	else if (match(fp, "="))
	{
		strcpy(id, "=");
		token = 25;
	}
	else if (match(fp, ";"))
	{
		strcpy(id, ";");
		token = 26;
	}
	else if (match(fp, "("))
	{
		strcpy(id, "(");
		token = 27;
	}
	else if (match(fp, ")"))
	{
		strcpy(id, ")");
		token = 28;
	}
	else if (match(fp, "#"))
	{
		strcpy(id, "#");
		token = 0;
	}
	else if (isNum(fp))
	{
		token = 11;
	}
	else if (isId(fp))
	{
		token = 10;
	}
	else
	{
		//char temp = getc(fp);
		char temp = getc(fp);
		token = -1;
	}

}

int match(FILE *fp, char* str)
{
	char temp;
	int i;
	for (i = 0; i < strlen(str); i++)
	{
		temp = getc(fp);
		if (temp != str[i])break;
	}
	if (strlen(str) == i)
	{
		return 1;
	}
	else
	{
		fseek(fp, -i - 1, SEEK_CUR);
		return 0;
	}
}

int isId(FILE *fp)
{
	int len;
	char temp;
	temp = getc(fp);
	if (isalpha(temp))
	{
		id[0] = '\0';
		int i = 0;
		do
		{
			id[i] = temp;
			id[i + 1] = '\0';
			temp = getc(fp);
			i++;
		} while (isalnum(temp));
		fseek(fp, -1, SEEK_CUR);
		return 1;
	}
	fseek(fp, -1, SEEK_CUR);
	return 0;
}

int isNum(FILE *fp)
{
	int len;
	char temp;
	temp = getc(fp);
	if (isdigit(temp))
	{
		id[0] = '\0';
		int i = 0;
		while (isdigit(temp))
		{
			id[i] = temp;
			id[i + 1] = '\0';
			temp = getc(fp);
			i++;
		}
		num = atoi(id);
		fseek(fp, -1, SEEK_CUR);
		return 1;
	}
	fseek(fp, -1, SEEK_CUR);
	return 0;
}

int main(int argc, const char *argv[])
{
	if(argc < 2) {
		printf("insufficient args\n");
		return 1;
	}
	FILE *fp = fopen(argv[1], "r");
	do {
		lexical(fp);
		switch(token) {
			case 10: printf("(id, %s)\n", id); break;
			case 11: printf("(num, %d)\n", num); break;
			case -1: printf("error!\n"); break;
			default: printf("(%d, %s)\n", token, id); 		
		}
	} while(token != 0);
	

	fclose(fp);
	return 0;
}
